<template>
  <div class="container">
    <div class="mb-2">
      <!-- <input
        v-model="innerUrl"
        class="border rounded px-2 py-1 w-[520px]"
        placeholder="点击开始后自动加载播放地址"
        readonly
      /> -->
      <button
        @click="start"
        class="px-3 py-1 rounded bg-green-600 text-white hover:bg-green-700"
      >
        开始
      </button>
      <button
        @click="stop"
        class="px-3 py-1 rounded bg-red-600 text-white hover:bg-red-700"
      >
        停止
      </button>
    </div>

    <video
      ref="videoRef"
      class="w-full bg-black"
      :muted="muted"
      autoplay
      playsinline
      controls
    ></video>

    <p v-if="statusMsg" class="text-sm text-gray-500 mt-2">{{ statusMsg }}</p>
  </div>
</template>

<script setup>
import { ref, onUnmounted } from "vue";
import Hls from "hls.js";

// 同域部署：留空使用相对路径，彻底避免 CORS
const BACKEND_BASE = "http://8.148.149.77"; // ← 关键修改
const DEVICE_ID = "34020000001320000801";

const videoRef = ref(null);
const hlsIns = ref(null);
const innerUrl = ref("");
const statusMsg = ref("");
const muted = ref(true);

// 把后端返回的播放地址归一到同源（如果不小心返回了 127.0.0.1/localhost）
function normalizePlayUrl(u) {
  try {
    if (!u) return u;
    if (u.startsWith("/")) return u;
    const parsed = new URL(u);
    const isLoopback = ["127.0.0.1", "localhost"].includes(parsed.hostname);
    // 返回相对路径，让浏览器以当前域为基准请求
    return isLoopback ? parsed.pathname + parsed.search + parsed.hash : u;
  } catch {
    return u;
  }
}

async function fetchM3u8Url() {
  try {
    const res = await fetch(`${BACKEND_BASE}/api/play/${DEVICE_ID}`); // ← 关键修改：相对路径
    if (!res.ok) throw new Error(`后端HTTP错误 ${res.status}`);
    const data = await res.json();
    if (data.code !== 0 || !data.data?.play_url)
      throw new Error(data.msg || "返回数据异常");
    return normalizePlayUrl(data.data.play_url);
  } catch (e) {
    console.error(e);
    statusMsg.value = "获取播放地址失败：" + e.message;
    return null;
  }
}

function destroyPlayer() {
  try {
    if (hlsIns.value) {
      hlsIns.value.destroy();
      hlsIns.value = null;
    }
    const v = videoRef.value;
    if (v) {
      v.pause();
      v.removeAttribute("src");
      v.load();
    }
  } catch {}
}

async function start() {
  statusMsg.value = "请求播放地址中...";
  const url = await fetchM3u8Url();
  if (!url) return;

  innerUrl.value = url;
  statusMsg.value = "正在连接...";
  const v = videoRef.value;
  destroyPlayer();

  if (v.canPlayType("application/vnd.apple.mpegurl")) {
    v.src = url;
    v.play().catch(() => {
      v.muted = true;
      v.play().catch(() => {
        statusMsg.value = "需要点击“开始”触发播放";
      });
    });
  } else if (Hls.isSupported()) {
    hlsIns.value = new Hls({
      lowLatencyMode: true,
      maxBufferLength: 10,
      manifestLoadingMaxRetry: 10,
      manifestLoadingRetryDelay: 800,
      manifestLoadingTimeOut: 5000,
      fragLoadingMaxRetry: 6,
      fragLoadingRetryDelay: 800,
      fragLoadingTimeOut: 8000,
    });
    hlsIns.value.loadSource(url);
    hlsIns.value.attachMedia(v);

    hlsIns.value.on(Hls.Events.MANIFEST_PARSED, () => {
      v.play().catch(() => {
        v.muted = true;
        v.play().catch(() => {
          statusMsg.value = "需要点击“开始”触发播放";
        });
      });
    });

    hlsIns.value.on(Hls.Events.ERROR, (ev, data) => {
      if (
        data?.type === Hls.ErrorTypes.NETWORK_ERROR &&
        (data?.details === Hls.ErrorDetails.MANIFEST_LOAD_ERROR ||
          data?.details === Hls.ErrorDetails.MANIFEST_LOAD_TIMEOUT)
      ) {
        setTimeout(() => {
          hlsIns.value?.loadSource(url);
          hlsIns.value?.startLoad();
        }, 1000);
      } else {
        statusMsg.value = `播放错误: ${data?.type || "unknown"}/${
          data?.details || ""
        }`;
        console.error("hls.js error", data);
      }
    });
  } else {
    statusMsg.value = "当前浏览器不支持 HLS";
    return;
  }

  v.onplaying = () => (statusMsg.value = "正在播放");
  v.onpause = () => (statusMsg.value = "已暂停");
  v.onwaiting = () => (statusMsg.value = "缓冲中...");
  v.onstalled = () => (statusMsg.value = "网络不稳定，可能卡顿");
}

function stop() {
  destroyPlayer();
  statusMsg.value = "已停止";
}

onUnmounted(() => {
  destroyPlayer();
});
</script>

<style scoped>
/* 可按需美化样式 */
.container {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.bg-black {
  width: 100%;
  height: 90%;
}
</style>
